home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Add-Ons / MPW / MPW re2c 1.1 / dfa.cc < prev    next >
Encoding:
Text File  |  1995-09-08  |  4.5 KB  |  230 lines  |  [TEXT/MPS ]

  1. // $Log: dfa.cc,v $
  2. //Revision 1.1  1994/04/08  15:27:59  peter
  3. //Initial revision
  4. //
  5.  
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include "globals.h"
  10. #include "substr.h"
  11. #include "dfa.h"
  12.  
  13. inline char octCh(uint c){
  14.     return '0' + c%8;
  15. }
  16.  
  17. void prtCh(ostream &o, uchar c){
  18.     uchar oc = talx[c];
  19.     switch(oc){
  20.     case '\'': o << "\\'"; break;
  21.     case '\n': o << "\\n"; break;
  22.     case '\t': o << "\\t"; break;
  23.     case '\v': o << "\\v"; break;
  24.     case '\b': o << "\\b"; break;
  25.     case '\r': o << "\\r"; break;
  26.     case '\f': o << "\\f"; break;
  27.     case '\a': o << "\\a"; break;
  28.     case '\\': o << "\\\\"; break;
  29.     default:
  30.     if(isprint(oc))
  31.         o << (char) oc;
  32.     else
  33.         o << '\\' << octCh(c/64) << octCh(c/8) << octCh(c);
  34.     }
  35. }
  36.  
  37. void printSpan(ostream &o, uint lb, uint ub){
  38.     if(lb > ub)
  39.     o << "*";
  40.     o << "[";
  41.     if((ub - lb) == 1){
  42.     prtCh(o, lb);
  43.     } else {
  44.     prtCh(o, lb);
  45.     o << "-";
  46.     prtCh(o, ub-1);
  47.     }
  48.     o << "]";
  49. }
  50.  
  51. uint Span::show(ostream &o, uint lb){
  52.     if(to){
  53.     printSpan(o, lb, ub);
  54.     o << " " << to->label << "; ";
  55.     }
  56.     return ub;
  57. }
  58.  
  59. ostream& operator<<(ostream &o, const State &s){
  60.     o << "state " << s.label;
  61.     if(s.rule)
  62.     o << " accepts " << s.rule->accept;
  63.     o << "\n";
  64.     uint lb = 0;
  65.     for(uint i = 0; i < s.go.nSpans; ++i)
  66.     lb = s.go.span[i].show(o, lb);
  67.     return o;
  68. }
  69.  
  70. ostream& operator<<(ostream &o, const DFA &dfa){
  71.     for(State *s = dfa.head; s; s = s->next)
  72.     o << s << "\n\n";
  73.     return o;
  74. }
  75.  
  76. State::State() : rule(NULL), action(NULL), link(NULL), kCount(0), kernel(NULL) {
  77.     go.nSpans = 0;
  78.     go.span = NULL;
  79. }
  80.  
  81. State::~State(){
  82.     delete kernel;
  83.     delete go.span;
  84. }
  85.  
  86. static Ins **closure(Ins **cP, Ins *i){
  87.     while(!isMarked(i)){
  88.     mark(i);
  89.     *(cP++) = i;
  90.     if(i->i.tag == FORK){
  91.         cP = closure(cP, i + 1);
  92.         i = (Ins*) i->i.link;
  93.     } else if(i->i.tag == GOTO){
  94.         i = (Ins*) i->i.link;
  95.     } else
  96.         break;
  97.     }
  98.     return cP;
  99. }
  100.  
  101. struct GoTo {
  102.     Char    ch;
  103.     void    *to;
  104. };
  105.  
  106. DFA::DFA(Ins *ins, uint ni, uint lb, uint ub, Char *rep)
  107.     : lbChar(lb), ubChar(ub) {
  108.     Ins **work = new Ins*[ni+1];
  109.     uint nc = ub - lb;
  110.     GoTo *goTo = new GoTo[nc];
  111.     Span *span = new Span[nc];
  112.     memset((char*) goTo, 0, nc*sizeof(GoTo));
  113.     tail = &head;
  114.     head = NULL;
  115.     nStates = 0;
  116.     toDo = NULL;
  117.     findState(work, closure(work, &ins[0]) - work);
  118.     while(toDo){
  119.     State *s = toDo;
  120.     toDo = s->link;
  121.  
  122.     Ins **cP, **iP, *i;
  123.     uint nGoTos = 0;
  124.  
  125.     s->rule = NULL;
  126.     for(iP = s->kernel; i = *iP; ++iP){
  127.         if(i->i.tag == CHAR){
  128.         for(Ins *j = i + 1; j < (Ins*) i->i.link; ++j){
  129.             if(!(j->c.link = goTo[j->c.value - lb].to))
  130.             goTo[nGoTos++].ch = j->c.value;
  131.             goTo[j->c.value - lb].to = j;
  132.         }
  133.         } else if(i->i.tag == TERM){
  134.         if(!s->rule || ((RuleOp*) i->i.link)->accept < s->rule->accept)
  135.             s->rule = (RuleOp*) i->i.link;
  136.         }
  137.     }
  138.  
  139.     uint j;
  140.     
  141.     for(j = 0; j < nGoTos; ++j){
  142.         GoTo *go = &goTo[goTo[j].ch - lb];
  143.         i = (Ins*) go->to;
  144.         for(cP = work; i; i = (Ins*) i->c.link)
  145.         cP = closure(cP, i + i->c.bump);
  146.         go->to = findState(work, cP - work);
  147.     }
  148.  
  149.     s->go.nSpans = 0;
  150.     for(j = 0; j < nc;){
  151.         State *to = (State*) goTo[rep[j]].to;
  152.         while(++j < nc && goTo[rep[j]].to == to);
  153.         span[s->go.nSpans].ub = lb + j;
  154.         span[s->go.nSpans].to = to;
  155.         s->go.nSpans++;
  156.     }
  157.  
  158.     for(j = nGoTos; j-- > 0;)
  159.         goTo[goTo[j].ch - lb].to = NULL;
  160.  
  161.     s->go.span = new Span[s->go.nSpans];
  162.     memcpy((char*) s->go.span, (char*) span, s->go.nSpans*sizeof(Span));
  163.  
  164.     (void) new Match(s);
  165.  
  166.     }
  167.     delete work;
  168.     delete goTo;
  169.     delete span;
  170. }
  171.  
  172. DFA::~DFA(){
  173.     State *s;
  174.     while(s = head){
  175.     head = s->next;
  176.     delete s;
  177.     }
  178. }
  179.  
  180. void DFA::addState(State **a, State *s){
  181.     s->label = nStates++;
  182.     s->next = *a;
  183.     *a = s;
  184.     if(a == tail)
  185.     tail = &s->next;
  186. }
  187.  
  188. State *DFA::findState(Ins **kernel, uint kCount){
  189.     Ins **cP, **iP, *i;
  190.  
  191.     kernel[kCount] = NULL;
  192.  
  193.     cP = kernel;
  194.     for(iP = kernel; i = *iP; ++iP){
  195.      if(i->i.tag == CHAR || i->i.tag == TERM){
  196.          *cP++ = i;
  197.     } else {
  198.          unmark(i);
  199.     }
  200.     }
  201.     kCount = cP - kernel;
  202.     kernel[kCount] = NULL;
  203.  
  204.     State * s;
  205.     
  206.     for(s = head; s; s = s->next){
  207.      if(s->kCount == kCount){
  208.          for(iP = s->kernel; i = *iP; ++iP)
  209.          if(!isMarked(i))
  210.              goto nextState;
  211.          goto unmarkAll;
  212.      }
  213.      nextState:;
  214.     }
  215.  
  216.     s = new State;
  217.     addState(tail, s);
  218.     s->kCount = kCount;
  219.     s->kernel = new Ins*[kCount+1];
  220.     memcpy(s->kernel, kernel, (kCount+1)*sizeof(Ins*));
  221.     s->link = toDo;
  222.     toDo = s;
  223.  
  224. unmarkAll:
  225.     for(iP = kernel; i = *iP; ++iP)
  226.      unmark(i);
  227.  
  228.     return s;
  229. }
  230.